import math
import subprocess

from video_base import VideoBase


class VideoCut(VideoBase):
    def __init__(self,
                 input_video_path: str,
                 output_prefix="video_part_",
                 start_index: int = 0,
                 split_duration: float = None,
                 split_size: int = None,
                 output_name="cut_start_end.mp4"):
        """
        input_video_path: 切割视频地址
        output_prefix: 输出视频前缀
        start_index: 排序开始
        split_duration: 每段切割时长（秒）
        split_size: 每段切割大小(MB)
        output_name: 输出视频名称
        """
        self.input_video_path = input_video_path
        self.output_prefix = output_prefix
        self.split_duration = split_duration
        self.start_index = start_index
        self.split_size = split_size
        self.output_name = output_name
        super().__init__(self.input_video_path)
        # 切割段数
        self.parts = None

    def _get_bitrate(self):
        """
        使用 ffprobe 获取视频码率 (bitrate)，单位 bit/s
        """
        cmd = [
            self.ffmpeg_exe,
            "-i", self.input_video_path
        ]
        result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        text = result.stderr.decode("utf-8", errors="ignore")

        import re
        m = re.search(r"bitrate: (\d+) kb/s", text)
        if m:
            bitrate_kbps = int(m.group(1))
            print(f"视频码率: {bitrate_kbps} kbps")
            return bitrate_kbps * 1000  # 转换为 bit/s

        print("⚠ 未能识别码率，默认 2Mbps")
        return 2_000_000

    def cut_video(self, start, duration, output_name):
        """执行 FFmpeg 片段裁剪"""
        print(f"[切割] 生成文件: {output_name}, start={start}, duration={duration}")
        cmd = [
            self.ffmpeg_exe,
            "-ss", str(start),
            "-i", self.input_video_path,
            "-t", str(duration),
            "-c:v", "copy",
            "-c:a", "copy",
            output_name
        ]
        print("执行命令:", " ".join(cmd))

        try:
            subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        except subprocess.CalledProcessError as e:
            print(f"❌ FFmpeg 执行失败: {e}")
            raise

    def video_cut_by_duration(self, part_index, duration=None):
        """
        按视频时长切割
        :param part_index:第几段
        :param duration:切割时长
        :return:
        """
        if duration is None:
            duration = self.split_duration
        index = self.start_index + part_index
        output_name = f"{self.output_prefix}{index}.mp4"
        start_time = part_index * duration
        duration = min(duration, self.duration - start_time)
        print(f"切割视频: {output_name}, start={start_time}, duration={duration}")
        self.cut_video(start_time, duration, output_name)

    def video_cut_by_size(self, max_size_mb=None):
        """
        根据最大文件大小（MB）切割视频
        """

        # 获取码率
        bitrate = self._get_bitrate()

        # 计算最大允许的单段秒数
        if max_size_mb is None:
            max_size_mb = self.split_size
        max_bytes = max_size_mb * 1024 * 1024
        max_bits = max_bytes * 8
        max_duration = max_bits / bitrate

        print(f"最大大小 = {max_size_mb}MB → 最大时长约 = {max_duration:.2f} 秒（{max_duration / 60:.2f} 分钟）")

        # 计算分段数量
        parts = math.ceil(self.duration / int(max_duration))
        print(f"视频总时长 {self.duration:.2f} 秒，将切割成 {parts} 段")

        for part_index in range(parts):
            self.video_cut_by_duration(part_index, max_duration)

        print("-------------------------------=== 视频按大小切割完毕 ===-------------------------------")

    def video_cut_start_end(self, start_time=0, end_len: int = 0, output_name=None):
        """

        :param start_time:开始时间
        :param end_len:结束时间
        :param output_name:输出名称
        :return:
        """
        if output_name is None:
            output_name = self.output_name
        duration = self.duration - start_time - end_len
        self.cut_video(start_time, duration, output_name)

    def video_cut_2_sections(self, split_time=0, output_prefix=None):
        """
        将视频文件按切割时间位置切割成2部分
        :param split_time:切割时间
        :param output_prefix:分段名称
        :return:
        """
        if output_prefix is None:
            output_prefix = self.output_prefix
        if split_time <= 0 or split_time >= self.duration:
            raise ValueError(f"split_time 必须在 (0, {self.duration}) 之间")

        self.cut_video(0, split_time, f"{output_prefix}{self.start_index}.mp4")
        self.cut_video(split_time, self.duration - split_time, f"{output_prefix}{self.start_index + 1}.mp4")

    def run(self, cut_type: str = "duration"):
        if cut_type == "duration" and self.split_duration is not None:
            total_parts = int((self.duration + self.split_duration - 1) // self.split_duration)
            for i in range(total_parts):
                self.video_cut_by_duration(i)
        elif cut_type == "size" and self.split_size is not None:
            self.video_cut_by_size()

        else:
            raise ValueError("请指定有效的 cut_type 或参数")


# ---------------- 使用示例 ----------------
if __name__ == "__main__":
    video_manager = VideoCut(input_video_path="video.mp4",
                             output_prefix="video_part_",
                             split_duration=2 * 60,
                             split_size=190)
    video_manager.run("size")
